const io = require('socket.io-client');
const isDev = require('electron-is-dev');

const signalTypes = require('../../signal_types');
const signal = require('./signalBus');
const signalServerStatus = require("../../signal_server_status");
const {settings_store} = require('../store');
const {log} = require('../../utils/log');

const initSignalClient = () => {
  // todo 因为我们是在electron的main进程中启动的, 这里没有localStorage, 想要debug需要自己打log
  // isDev && (localStorage.debug = '*');

  log('--- --- --- initSignalClient --- --- ---');
  log('process.env.SIGNAL_SEVER_URL:',process.env.SIGNAL_SEVER_URL);

  // 注意: 我们这里肯定是跨域(我们客户端是用electron起的), So在服务器端上socket.io初始化时,要加上一句cors:true
  const SignalClient = io(
    process.env.SIGNAL_SEVER_URL,
    {
      reconnection: false,
      timeout: process.env.SIGNAL_SERVER_CONNECT_TIMEOUT_TIME, //socket.io给的默认值是 20000
      autoConnect: false  //默认为true
      /*
         设置为false后, 就需要以下这样连接
         socket.connect();
         // or
         socket.io.open(err=>{});
     */
    }
  );

  // 第一次如果使用 socket.io.open(err=>{}) 是不会触发 connection事件的(不论本地的还是服务端的)
  SignalClient.connect();
  let first = true;
  // Fired when an namespace middleware error occurs.
  SignalClient.on('connect_error',()=>{
    log('--- --- --- connect_error --- --- ---')
    if(!first) return;
    first = false;
    tryToConnectForSeconds()
  });


  let timer;
  const reconnect = ()=>{
    SignalClient.io.open((err) => {
      if (err) return;

      if(timer){
        clearInterval(timer);
        timer = null;
        //不用在这里手动 signal.emit(signalTypes['SIGNAL_SERVER:STATE_CHANGED'])
        //因为重新连上时会触发 SignalClient.on('connect'), 这里面触发了
      }
    });
  }

  //一段时间内不停请求, 然后歇一会,  再不停请求, 这样方便失联时 我们ui上好展示 正在连接 (而不是现在这样一闪就过,立马变成failed)
  const tryToConnectForSeconds = () => {
    log('tryToConnectForSeconds 正在重连 --- --- ---');
    signal.emit(signalTypes["SIGNAL_SERVER:STATE_CHANGED"], signalServerStatus.CONNECTING);
    timer = setInterval(()=>{
      reconnect()
    },500)
    setTimeout(() => {
      if(!timer) return;
      log('终止重连 --- --- ---')
      clearInterval(timer);
      timer = null;
      signal.emit(signalTypes["SIGNAL_SERVER:STATE_CHANGED"], signalServerStatus.CONNECT_FAILED);
    }, process.env.SIGNAL_SERVER_RECONNECTION_DURATION_TIME);
  };
  //
  /*const tryReconnect = () => {
    log(`${process.env.SIGNAL_SERVER_RECONNECTION_TIME}ms后重连`);
    setTimeout(() => {
      log('正在重连 --- --- ---');
      signal.emit(signalTypes["SIGNAL_SERVER:STATE_CHANGED"], signalServerStatus.CONNECTING);
      SignalClient.io.open((err) => {
        if (err) {
          log('socket.io.open err --- --- ---');
          signal.emit(signalTypes["SIGNAL_SERVER:STATE_CHANGED"], signalServerStatus.CONNECT_FAILED);
          tryReconnect();
        }
      });

    }, process.env.SIGNAL_SERVER_RECONNECTION_TIME);
  }*/

  //服务器挂掉的时候 只会触发disconnect, 而不会触发 connect_error (或socket.io.on('error'))
  SignalClient.on("disconnect", () => {
    log('disconnect--- --- ---');
    signal.emit(signalTypes["SIGNAL_SERVER:STATE_CHANGED"], signalServerStatus.CONNECT_FAILED);
    tryToConnectForSeconds()
  });


  SignalClient.on('connect', () => {
    if(first) first = false;
    log('connection successful --- --- --');
    //连接成功 登录注册进服务器
    signal.emit(signalTypes["SIGNAL_SERVER:LOGIN"]);

    signal.emit(signalTypes['SIGNAL_SERVER:STATE_CHANGED'], signalServerStatus.CONNECTED);
  });

  // handle the event sent with socket.send()
  SignalClient.on('message', (event_type, data) => {
    // 接受到的所有socket.io服务器发来的消息 都会通过signal转发
    signal.emit(event_type, data);
  });

  //如果是转发的消息会多接受一个sender参数, 为发送者的idcode
  signal.send = (event_type, data, sender) => {
    //socket.io会自动序列化以及反序列化
    SignalClient.send(event_type, data, sender);
  };

  signal.on(signalTypes["SIGNAL_SERVER:TRY_TO_CONNECT_FOR_SECONDS"], () => {
    tryToConnectForSeconds();
  });
  signal.on(signalTypes["SIGNAL_SERVER:LOGIN"], () => {
    log('已有identifier_code,为:', settings_store.get('identifier_code'));

    SignalClient.send(signalTypes["SIGNAL_SERVER:LOGIN"],{
      identifier_code:
        isDev ?
          ''
          : settings_store.get('identifier_code') || '',
      needCaptcha: settings_store.get('needCaptcha') || false
    })
  });
};

module.exports = initSignalClient;
